/*!
 * \file test_ini_helper.cpp
 * \brief IniHelper工具类的单元测试
 * 
 * \details 测试IniHelper类的所有功能，包括：
 *          - INI文件的加载和保存
 *          - 各种数据类型的读写操作
 *          - 节和键的管理功能
 *          - 异常处理和边界条件
 *          - 批量数据操作
 */

#include <gtest/gtest.h>
#include <fstream>
#include <cstdio>
#include "IniHelper.hpp"

/*!
 * \brief IniHelper测试夹具类
 * 
 * \details 为IniHelper测试提供统一的测试环境，包括：
 *          - 测试文件的创建和清理
 *          - 通用的测试数据准备
 *          - 测试后的资源清理
 */
class IniHelperTest : public ::testing::Test {
protected:
    void SetUp() override {
        // 创建测试用的INI文件
        test_file = "test_config.ini";
        sample_file = "sample_config.ini";
        
        // 创建示例INI文件内容
        createSampleIniFile();
    }

    void TearDown() override {
        // 清理测试文件
        std::remove(test_file.c_str());
        std::remove(sample_file.c_str());
        std::remove("output_test.ini");
        std::remove("empty_test.ini");
    }

    /*!
     * \brief 创建示例INI文件
     * 
     * \details 创建包含各种数据类型的示例INI文件，用于测试读取功能
     */
    void createSampleIniFile() {
        std::ofstream file(sample_file);
        file << "[database]\n";
        file << "host=localhost\n";
        file << "port=3306\n";
        file << "username=admin\n";
        file << "password=secret123\n";
        file << "timeout=30\n";
        file << "ssl_enabled=true\n";
        file << "max_connections=100\n";
        file << "connection_timeout=5.5\n";
        file << "\n";
        file << "[logging]\n";
        file << "level=INFO\n";
        file << "file_path=/var/log/app.log\n";
        file << "max_size=10485760\n";
        file << "rotate=true\n";
        file << "compress=false\n";
        file << "\n";
        file << "[performance]\n";
        file << "cache_size=1024\n";
        file << "thread_count=8\n";
        file << "enable_optimization=true\n";
        file << "memory_limit=2.5\n";
        file.close();
    }

    std::string test_file;
    std::string sample_file;
};

/*!
 * \brief 测试INI文件加载功能
 * 
 * \details 验证IniHelper能否正确加载存在和不存在的INI文件
 */
TEST_F(IniHelperTest, TestLoadFile) {
    IniHelper ini;
    
    // 测试加载不存在的文件
    ini.load("non_existent_file.ini");
    EXPECT_TRUE(ini.isLoaded());  // 即使文件不存在，isLoaded也应该返回true
    
    // 测试加载存在的文件
    IniHelper ini2;
    ini2.load(sample_file.c_str());
    EXPECT_TRUE(ini2.isLoaded());
    
    // 验证能读取到正确的值
    std::string host = ini2.readString("database", "host", "default");
    EXPECT_EQ(host, "localhost");
}

/*!
 * \brief 测试字符串读写功能
 * 
 * \details 验证字符串类型数据的读取和写入操作
 */
TEST_F(IniHelperTest, TestStringReadWrite) {
    IniHelper ini;
    ini.load(sample_file.c_str());
    
    // 测试读取存在的字符串值
    EXPECT_EQ(ini.readString("database", "host"), "localhost");
    EXPECT_EQ(ini.readString("database", "username"), "admin");
    EXPECT_EQ(ini.readString("logging", "level"), "INFO");
    
    // 测试读取不存在的值（使用默认值）
    EXPECT_EQ(ini.readString("database", "nonexistent", "default"), "default");
    EXPECT_EQ(ini.readString("nonexistent_section", "key", "fallback"), "fallback");
    
    // 测试写入字符串值
    ini.writeString("database", "new_host", "192.168.1.100");
    EXPECT_EQ(ini.readString("database", "new_host"), "192.168.1.100");
    
    // 测试写入新节
    ini.writeString("new_section", "new_key", "new_value");
    EXPECT_EQ(ini.readString("new_section", "new_key"), "new_value");
}

/*!
 * \brief 测试整数读写功能
 * 
 * \details 验证整数类型数据的读取和写入操作
 */
TEST_F(IniHelperTest, TestIntegerReadWrite) {
    IniHelper ini;
    ini.load(sample_file.c_str());
    
    // 测试读取整数值
    EXPECT_EQ(ini.readInt("database", "port"), 3306);
    EXPECT_EQ(ini.readInt("database", "timeout"), 30);
    EXPECT_EQ(ini.readInt("database", "max_connections"), 100);
    EXPECT_EQ(ini.readInt("performance", "cache_size"), 1024);
    
    // 测试读取不存在的值（使用默认值）
    EXPECT_EQ(ini.readInt("database", "nonexistent", 9999), 9999);
    EXPECT_EQ(ini.readInt("nonexistent_section", "key", -1), -1);
    
    // 测试写入整数值
    ini.writeInt("database", "new_port", 5432);
    EXPECT_EQ(ini.readInt("database", "new_port"), 5432);
    
    // 测试负数
    ini.writeInt("test", "negative", -100);
    EXPECT_EQ(ini.readInt("test", "negative"), -100);
    
    // 测试零值
    ini.writeInt("test", "zero", 0);
    EXPECT_EQ(ini.readInt("test", "zero"), 0);
}

/*!
 * \brief 测试无符号整数读写功能
 * 
 * \details 验证无符号整数类型数据的读取和写入操作
 */
TEST_F(IniHelperTest, TestUnsignedIntegerReadWrite) {
    IniHelper ini;
    ini.load(sample_file.c_str());
    
    // 测试读取无符号整数值
    EXPECT_EQ(ini.readUInt("database", "port"), 3306U);
    EXPECT_EQ(ini.readUInt("logging", "max_size"), 10485760U);
    
    // 测试读取不存在的值（使用默认值）
    EXPECT_EQ(ini.readUInt("database", "nonexistent", 8888U), 8888U);
    
    // 测试写入无符号整数值
    ini.writeUInt("database", "buffer_size", 4096U);
    EXPECT_EQ(ini.readUInt("database", "buffer_size"), 4096U);
    
    // 测试大数值
    ini.writeUInt("test", "large_value", 4294967295U);
    EXPECT_EQ(ini.readUInt("test", "large_value"), 4294967295U);
}

/*!
 * \brief 测试布尔值读写功能
 * 
 * \details 验证布尔类型数据的读取和写入操作
 */
TEST_F(IniHelperTest, TestBooleanReadWrite) {
    IniHelper ini;
    ini.load(sample_file.c_str());
    
    // 测试读取布尔值
    EXPECT_TRUE(ini.readBool("database", "ssl_enabled"));
    EXPECT_TRUE(ini.readBool("logging", "rotate"));
    EXPECT_FALSE(ini.readBool("logging", "compress"));
    EXPECT_TRUE(ini.readBool("performance", "enable_optimization"));
    
    // 测试读取不存在的值（使用默认值）
    EXPECT_TRUE(ini.readBool("database", "nonexistent", true));
    EXPECT_FALSE(ini.readBool("database", "nonexistent", false));
    
    // 测试写入布尔值
    ini.writeBool("database", "auto_commit", true);
    EXPECT_TRUE(ini.readBool("database", "auto_commit"));
    
    ini.writeBool("database", "read_only", false);
    EXPECT_FALSE(ini.readBool("database", "read_only"));
}

/*!
 * \brief 测试浮点数读写功能
 * 
 * \details 验证浮点数类型数据的读取和写入操作
 */
TEST_F(IniHelperTest, TestDoubleReadWrite) {
    IniHelper ini;
    ini.load(sample_file.c_str());
    
    // 测试读取浮点数值
    EXPECT_DOUBLE_EQ(ini.readDouble("database", "connection_timeout"), 5.5);
    EXPECT_DOUBLE_EQ(ini.readDouble("performance", "memory_limit"), 2.5);
    
    // 测试读取不存在的值（使用默认值）
    EXPECT_DOUBLE_EQ(ini.readDouble("database", "nonexistent", 3.14), 3.14);
    
    // 测试写入浮点数值
    ini.writeDouble("database", "retry_delay", 1.5);
    EXPECT_DOUBLE_EQ(ini.readDouble("database", "retry_delay"), 1.5);
    
    // 测试精度
    ini.writeDouble("test", "precision", 3.141592653589793);
    EXPECT_NEAR(ini.readDouble("test", "precision"), 3.141592653589793, 1e-10);
    
    // 测试负数
    ini.writeDouble("test", "negative", -2.5);
    EXPECT_DOUBLE_EQ(ini.readDouble("test", "negative"), -2.5);
}

/*!
 * \brief 测试节操作功能
 * 
 * \details 验证INI文件节的读取和管理功能
 */
TEST_F(IniHelperTest, TestSectionOperations) {
    IniHelper ini;
    ini.load(sample_file.c_str());
    
    // 测试读取所有节
    FieldArray sections;
    int count = ini.readSections(sections);
    EXPECT_GT(count, 0);
    EXPECT_GE(sections.size(), 3);  // 至少应该有database, logging, performance三个节
    
    // 验证特定节存在
    bool found_database = false, found_logging = false, found_performance = false;
    for (const auto& section : sections) {
        if (section == "database") found_database = true;
        if (section == "logging") found_logging = true;
        if (section == "performance") found_performance = true;
    }
    EXPECT_TRUE(found_database);
    EXPECT_TRUE(found_logging);
    EXPECT_TRUE(found_performance);
}

/*!
 * \brief 测试键操作功能
 * 
 * \details 验证INI文件键的读取功能
 */
TEST_F(IniHelperTest, TestKeyOperations) {
    IniHelper ini;
    ini.load(sample_file.c_str());
    
    // 测试读取指定节的所有键
    FieldArray keys;
    int count = ini.readSecKeyArray("database", keys);
    EXPECT_GT(count, 0);
    EXPECT_GE(keys.size(), 6);  // database节应该有多个键
    
    // 验证特定键存在
    bool found_host = false, found_port = false;
    for (const auto& key : keys) {
        if (key == "host") found_host = true;
        if (key == "port") found_port = true;
    }
    EXPECT_TRUE(found_host);
    EXPECT_TRUE(found_port);
    
    // 测试不存在的节
    FieldArray empty_keys;
    int empty_count = ini.readSecKeyArray("nonexistent_section", empty_keys);
    EXPECT_EQ(empty_count, 0);
    EXPECT_TRUE(empty_keys.empty());
}

/*!
 * \brief 测试键值对操作功能
 * 
 * \details 验证INI文件键值对的批量读取功能
 */
TEST_F(IniHelperTest, TestKeyValueOperations) {
    IniHelper ini;
    ini.load(sample_file.c_str());
    
    // 测试读取指定节的所有键值对
    FieldArray keys, values;
    int count = ini.readSecKeyValArray("database", keys, values);
    EXPECT_GT(count, 0);
    EXPECT_EQ(keys.size(), values.size());
    
    // 验证键值对的对应关系
    for (size_t i = 0; i < keys.size(); ++i) {
        if (keys[i] == "host") {
            EXPECT_EQ(values[i], "localhost");
        } else if (keys[i] == "port") {
            EXPECT_EQ(values[i], "3306");
        } else if (keys[i] == "username") {
            EXPECT_EQ(values[i], "admin");
        }
    }
}

/*!
 * \brief 测试删除操作功能
 * 
 * \details 验证键值对和节的删除功能
 */
TEST_F(IniHelperTest, TestRemoveOperations) {
    IniHelper ini;
    ini.load(sample_file.c_str());
    
    // 验证键存在
    EXPECT_EQ(ini.readString("database", "host"), "localhost");
    
    // 删除键值对
    ini.removeValue("database", "host");
    EXPECT_EQ(ini.readString("database", "host", "not_found"), "not_found");
    
    // 验证节存在
    EXPECT_GT(ini.readInt("database", "port", -1), 0);
    
    // 删除整个节
    ini.removeSection("database");
    EXPECT_EQ(ini.readInt("database", "port", -1), -1);
    
    // 测试删除不存在的键和节（应该不抛出异常）
    ini.removeValue("nonexistent_section", "nonexistent_key");
    ini.removeSection("nonexistent_section");
}

/*!
 * \brief 测试文件保存功能
 * 
 * \details 验证INI文件的保存和重新加载功能
 */
TEST_F(IniHelperTest, TestSaveFile) {
    IniHelper ini;
    ini.load(sample_file.c_str());
    
    // 修改一些值
    ini.writeString("database", "host", "modified_host");
    ini.writeInt("database", "port", 5432);
    ini.writeBool("database", "ssl_enabled", false);
    
    // 保存到新文件
    ini.save("output_test.ini");
    
    // 重新加载并验证
    IniHelper ini2;
    ini2.load("output_test.ini");
    
    EXPECT_EQ(ini2.readString("database", "host"), "modified_host");
    EXPECT_EQ(ini2.readInt("database", "port"), 5432);
    EXPECT_FALSE(ini2.readBool("database", "ssl_enabled"));
}

/*!
 * \brief 测试边界条件和异常情况
 * 
 * \details 验证各种边界条件和异常输入的处理
 */
TEST_F(IniHelperTest, TestBoundaryConditions) {
    IniHelper ini;
    
    // 测试未加载文件时的操作
    EXPECT_FALSE(ini.isLoaded());
    EXPECT_EQ(ini.readString("section", "key", "default"), "default");
    EXPECT_EQ(ini.readInt("section", "key", 999), 999);
    
    // 加载空文件
    std::ofstream empty_file("empty_test.ini");
    empty_file.close();
    
    ini.load("empty_test.ini");
    EXPECT_TRUE(ini.isLoaded());
    EXPECT_EQ(ini.readString("section", "key", "default"), "default");
    
    // 测试空字符串参数
    ini.writeString("test", "empty", "");
    EXPECT_EQ(ini.readString("test", "empty"), "");
    
    // 测试特殊字符
    ini.writeString("test", "special", "!@#$%^&*()");
    EXPECT_EQ(ini.readString("test", "special"), "!@#$%^&*()");
    
    // 测试长字符串
    std::string long_string(1000, 'A');
    ini.writeString("test", "long", long_string.c_str());
    EXPECT_EQ(ini.readString("test", "long"), long_string);
}

/*!
 * \brief 测试数据类型转换
 * 
 * \details 验证不同数据类型之间的转换处理
 */
TEST_F(IniHelperTest, TestTypeConversion) {
    IniHelper ini;
    
    // 写入字符串形式的数字
    ini.writeString("test", "string_int", "123");
    ini.writeString("test", "string_double", "3.14");
    ini.writeString("test", "string_bool", "true");
    
    // 尝试以不同类型读取
    EXPECT_EQ(ini.readInt("test", "string_int"), 123);
    EXPECT_DOUBLE_EQ(ini.readDouble("test", "string_double"), 3.14);
    EXPECT_TRUE(ini.readBool("test", "string_bool"));
    
    // 测试无效转换（应该返回默认值）
    ini.writeString("test", "invalid_int", "not_a_number");
    EXPECT_EQ(ini.readInt("test", "invalid_int", 999), 999);
    
    ini.writeString("test", "invalid_double", "not_a_double");
    EXPECT_DOUBLE_EQ(ini.readDouble("test", "invalid_double", 2.5), 2.5);
}

/*!
 * \brief 测试性能和大数据处理
 * 
 * \details 验证处理大量数据时的性能和稳定性
 */
TEST_F(IniHelperTest, TestPerformanceAndLargeData) {
    IniHelper ini;
    
    // 创建大量节和键值对
    for (int i = 0; i < 100; ++i) {
        std::string section = "section_" + std::to_string(i);
        for (int j = 0; j < 10; ++j) {
            std::string key = "key_" + std::to_string(j);
            std::string value = "value_" + std::to_string(i * 10 + j);
            ini.writeString(section.c_str(), key.c_str(), value.c_str());
        }
    }
    
    // 验证数据完整性
    EXPECT_EQ(ini.readString("section_50", "key_5"), "value_505");
    EXPECT_EQ(ini.readString("section_99", "key_9"), "value_999");
    
    // 测试节数量
    FieldArray sections;
    int section_count = ini.readSections(sections);
    EXPECT_EQ(section_count, 100);
    
    // 测试键数量
    FieldArray keys;
    int key_count = ini.readSecKeyArray("section_0", keys);
    EXPECT_EQ(key_count, 10);
} 